package me.flyray.crm.core.blockchain;

import java.math.BigDecimal;

import me.flyray.crm.core.blockchain.block.Block;
import me.flyray.crm.core.blockchain.block.Blockchain;
import me.flyray.crm.core.blockchain.transaction.Transaction;
import me.flyray.crm.core.blockchain.util.Base58Check;
import me.flyray.crm.core.blockchain.wallet.Wallet;
import me.flyray.crm.core.blockchain.wallet.WalletUtils;
import org.springframework.stereotype.Component;

/** 
* @author: bolei
* @date：2018年9月8日 上午9:35:10 
* @description：
*approve是授权第三方（比如某个服务合约）从发送者账户转移代币，然后通过 transferFrom() 函数来执行具体的转移操作。
*账户A有1000个ETH，想允许B账户随意调用他的100个ETH，过程如下：
*A账户按照以下形式调用approve函数approve(B,100)
*B账户想用这100个ETH中的10个ETH给C账户，调用transferFrom(A, C, 10)
*调用allowance(A, B)可以查看B账户还能够调用A账户多少个token
*后面两个是事件，事件是为了获取日志方便提供的。前者是在代币被转移时触发，后者是在调用approve方法时触发。
*/

@Component
public class ERC827Contract {
	
	/**
     * 创建钱包
     *
     * @throws Exception
     */
    public static Wallet createWallet() throws Exception {
        Wallet wallet = WalletUtils.getInstance().createWallet();
        return wallet;
    }
    
	/**
     * 返回ERC20代币的名字，例如”My test token”。
     */
    public String name(String name) {
        return null;
    }
    
    /**
     * 返回代币的简称，例如：MTT，这个也是我们一般在代币交易所看到的名字。
     */
    public String symbol(String symbol) {
        return null;
    }
    
    /**
     * 返回token使用的小数点后几位。比如如果设置为3，就是支持0.001表示。
     */
    public String decimals(String name) {
        return null;
    }
    
    
    /**
     * 返回某个地址(账户)的账户余额
     */
    public static String balanceOf(String address) {
    	// 检查钱包地址是否合法
        try {
            Base58Check.base58ToBytes(address);
        } catch (Exception e) {
            throw new RuntimeException("ERROR: invalid wallet address", e);
        }
        
        // 得到公钥Hash值
        //byte[] versionedPayload = Base58Check.base58ToBytes(address);
        //byte[] pubKeyHash = Arrays.copyOfRange(versionedPayload, 1, versionedPayload.length);
        //根据地址查询platform_unique_customer表取出余额
        int balance = 0;
        return String.valueOf(balance);
    }
    
    /**
     * 从代币合约的调用者地址上转移_value的数量token到的地址_to，并且必须触发Transfer事件。
     */
    public static String transfer(String address_to, String uint256_value) {
    	//默认从平台的合约账户出账 在商户账户表里 开通平台合约账户
    	//记录平台出账记录同时记录个人账户入账记录,顶级平台手续费收入入账
    	
        return null;
    }
    
    /**
     * 从地址_from发送数量为_value的token到地址_to,必须触发Transfer事件。
	 * transferFrom方法用于允许合同代理某人转移token。条件是from账户必须经过了approve。这个后面会举例说明。
     * @return 
     */
    public static void transferFrom(String from, String to, String _tokens) {
    	// 检查钱包地址是否合法
    	BigDecimal amount = new BigDecimal(_tokens);
        try {
            Base58Check.base58ToBytes(from);
        } catch (Exception e) {
            throw new RuntimeException("ERROR: sender address invalid ! address=" + from, e);
        }
        // 检查钱包地址是否合法
        try {
            Base58Check.base58ToBytes(to);
        } catch (Exception e) {
            throw new RuntimeException("ERROR: receiver address invalid ! address=" + to, e);
        }
        if (amount.compareTo(new BigDecimal(1)) == 0) {
            throw new RuntimeException("ERROR: amount invalid ! amount=" + amount);
        }
        // 新交易 将交易记录写到数据库中
        //每笔交易都有手续费,扣除手续之后入账，手续费入平台手续费收入账户
        
    }
    
    /**
     * 该功能批准或授予另一实体代表所有者转让代币的权限。 
     * 例如，如果爱丽丝拥有1个NFT，她可以为她的朋友鲍勃拨打批准功能。 
     * 通话成功后，鲍勃可以代表爱丽丝以后对该令牌进行所有权或执行操作。 
     */
    public String approve(String indexed_owner, String indexed_approved, String _tokenId) {
        return null;
    }
    
    /**
     * 返回_spender仍然被允许从_owner提取的金额。
     */
    public String allowance(String name) {
        return null;
    }
    
    
    /**
     * Returns the total amount of tokens in the given contract, 
     * this should be optional as assets might be allocated and issued on the fly. 
     * This means that supply is not always fixed.
     */
    public String totalSupply() {
        return null;
    }
    
    /**
     * A function which allows a user to sell a batch of non-fungible 
     * tokens without paying for the gas fee (only the buyer has to). 
     * This is achieved by signing an attestation containing the amount 
     * of tokens to sell, the contract address, an expiry timestamp, 
     * the price and a prefix containing the ERC spec name and chain id. 
     * A buyer can then pay for the deal in one transaction by attaching 
     * the appropriate ether to satisfy the deal.
     */
    public String trade(String expiryTimeStamp, String tokenIndices, String v, String r, String s) {
        return null;
    }
    
    /**
     * 该函数是返回Token拥有者的地址，
     * 由于每个ERC721令牌都是不可替代的，因此它们是唯一的，
     * 它通过唯一ID在区块链中引用，我们可以使用其ID来确定Token的所有者。
     */
    public String ownerOf(String _tokenId) {
        return null;
    }

    /**
     * 获取合约地址；
     */
    public String getContractAddress() {
    	return null;
    }
    
    /**
     * 创建区块链
     *
     * @param address
     */
    @SuppressWarnings("unused")
    public static Block createBlockchain(Transaction[] transactions) {
    	Blockchain blockchain = new Blockchain();
    	Block block = blockchain.mineBlock(transactions);
    	return block;
    }
    
}
